package com.xzcedu.reflection;

import com.xzcedu.Cat;

import java.io.FileInputStream;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Properties;

/**
 * @author 徐州城
 * @version 1.0
 */
@SuppressWarnings("all")
public class Reflection01 {
    public static void main(String[] args) throws Exception {
        //1. 使用Properties 类，可以读写配置文件
        Properties properties = new Properties();
        properties.load(new FileInputStream("src\\re.properties"));
        String classfullpath = properties.get("classfullpath").toString();//"com.xzcedu.Cat"
        String methodName = properties.get("method").toString();

        System.out.println("classfullpath=" + classfullpath);
        System.out.println("method=" + methodName);

        //2. 使用反射机制解决
        //(1) 加载类 返回一个Class类型的对象
        Class cls = Class.forName(classfullpath);
        //(2) 通过 cls 得到你加载的类 com.xzcedu.Cat 的对象实例
        Object o = cls.newInstance();
        System.out.println("o的运行类型=" + o.getClass());
        //(3) 通过 cls 得到你加载的类 com.xzcedu.Cat 的 methodName"hi" 的方法对象
        //    即：在反射中，可以把方法视为对象（万物皆对象）
        Method method = cls.getMethod(methodName);
        //(4) 通过method 调用方法: 即通过方法对象调用方法
        System.out.println("=============");
        method.invoke(o);//传统方法 对象.方法(), 反射机制 方法.invoke(对象)

        //java.lang.reflect.Field：代表类的成员变量, Field对象就表示某个类的成员变量
        //得到name字段
        //getField不能得到私有的属性
        Field nameField = cls.getField("age");
        System.out.println(nameField.get(o));//传统写法 对象.字段 , 反射：成员变量对象.get(Class对象实例)

        //java.lang.reflect.Constructor：代表类的构造方法, Constructor对象表示构造器
        Constructor constructor = cls.getConstructor();//() 中可以指定构造器参数类型，返回的是无参构造器
        System.out.println(constructor);

        Constructor constructor2 = cls.getConstructor(String.class);//这里传入的 String.class 就是String类的Class对象
        System.out.println(constructor2);

    }
}
